package javaer.starter.core.parser;

import javaer.starter.base.domain.dto.DependencyDTO;
import javaer.starter.base.domain.dto.ModuleDTO;
import javaer.starter.base.domain.dto.NewProjectDefinition;
import javaer.starter.base.domain.dto.PomParent;
import javaer.starter.constant.BuiltInKeywords;
import javaer.starter.constant.SymbolEnum;
import javaer.starter.core.metadata.PomXml;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * root pom解析
 *
 * @author yangzhen
 * @date 2021/11/17 15:50
 * @since 1.0.0
 */
@Component
public class RootPomXmlParser extends AbstractPomXmlParser {

    @Override
    public PomXml initPom(NewProjectDefinition projectDefinition, ModuleDTO module) {
        return new PomXml()
                .setImRootPom(true)
                .setImStarterPom(false)
                .setModuleId(module.getModuleId())
                .setGroupId(projectDefinition.getGroupId())
                .setArtifactId(getArtifactId(projectDefinition, module))
                .setVersion(projectDefinition.getVersion())
                .setBasePackage(projectDefinition.getBasePackage())
                .setDescription(projectDefinition.getDescription())
                .setModulePackage(getModulePackage(projectDefinition, module));
    }

    @Override
    public PomParent getParent(NewProjectDefinition projectDefinition) {
        PomParent pomParent = projectDefinition.getPomParent();
        if (pomParent == null || pomParent.getVersion() == null || pomParent.getArtifactId() == null || pomParent.getGroupId() == null) {
            DependencyDTO parentDep = dependencyService.findByTypeIdAndDepId(projectDefinition.getTypeId(), BuiltInKeywords.POM_PARENT.getValue());
            if (parentDep != null) {
                pomParent = new PomParent(parentDep.getGroupId(), parentDep.getArtifactId(), parentDep.getVersion());
            }
        }
        return pomParent;
    }

    @Override
    public Map<String, String> getProperties(NewProjectDefinition projectDefinition) {
        Map<String, String> properties = new LinkedHashMap<>();
        properties.put("revision", projectDefinition.getVersion());
        properties.put("maven.compiler.source", projectDefinition.getCompiler());
        properties.put("maven.compiler.target", projectDefinition.getCompiler());
        properties.put("project.build.sourceEncoding", "UTF-8");
        return properties;
    }

    @Override
    public List<PomXml> parse(NewProjectDefinition projectDefinition) throws Exception {
        ModuleDTO moduleDTO = new ModuleDTO();
        moduleDTO.setModuleId(BuiltInKeywords.ROOT.getValue());
        return Arrays.asList(doBuild(projectDefinition, moduleDTO));
    }

    @Override
    public Set<String> getModules(NewProjectDefinition projectDefinition, ModuleDTO module) {

        Set<ModuleDTO> moduleDTOS = moduleService.findByTypeId(projectDefinition.getTypeId());
        if (CollectionUtils.isEmpty(moduleDTOS)) {
            throw new RuntimeException("脚手架缺失模块信息");
        }

        // 区分模块是否必须
        Map<Boolean, Set<String>> moduleGroup = moduleDTOS.stream()
                .collect(Collectors.groupingBy(
                        moduleDTO -> moduleDTO.isRequired(),
                        Collectors.mapping(
                                moduleDTO -> moduleDTO.getModuleId(),
                                Collectors.toSet()
                        )
                ));
        Set<String> childModules = new HashSet<>();
        Set<String> required = moduleGroup.get(Boolean.TRUE);
        if (CollectionUtils.isNotEmpty(required)) {
            childModules.addAll(required);
        }

        Set<String> notRequired = moduleGroup.get(Boolean.FALSE);
        Set<String> moduleIds = projectDefinition.getModuleIds();
        if (CollectionUtils.isNotEmpty(notRequired)) {
            if (CollectionUtils.isNotEmpty(moduleIds)) {
                notRequired.retainAll(moduleDTOS);
            }
            childModules.addAll(notRequired);
        }

        if (childModules.isEmpty()) {
            throw new RuntimeException("没有选择模块数据，请重试");
        }

        Set<String> result = childModules.stream()
                .map(v -> projectDefinition.getArtifactId() + SymbolEnum.HORIZONTAL_LINE.getSymbol() + v.toLowerCase())
                .collect(Collectors.toSet());
        return result;
    }

    @Override
    protected Set<String> getDependencyModules(NewProjectDefinition projectDefinition, ModuleDTO module) {
        return null;
    }

    @Override
    public String getArtifactId(NewProjectDefinition projectDefinition, ModuleDTO module) {
        return projectDefinition.getArtifactId();
    }

    @Override
    protected String getModulePackage(NewProjectDefinition projectDefinition, ModuleDTO module) {
        return projectDefinition.getBasePackage();
    }
}
